/****************************************************************
 *This file is main.c
 ****************************************************************/

//本库使用的头文件
#include "libStandard_pxie.h"

#define BUFFER_LEN          409600

unsigned int  rd_from_fpga[BUFFER_LEN];
unsigned int  rd_fpga_len = 0;
unsigned int  wr_from_fpga[BUFFER_LEN];
unsigned int  wr_fpga_len = 0;   

/****************************************************************
 *main 函数为设备库的测试函数
 ****************************************************************/
int main(void)
{
    ViChar pxie_board_name[] = {"/dev/slot03_00_hitmc0_user"};

    ViSession pxie_fd = VI_NULL;

    int errStatus;
    unsigned int  temp_i;

    ViUInt16 vendor_id, pci_device_id, pci_slot_id, pci_bus_id;

    fprintf(stderr,"\n");
    fprintf(stderr,"\n");
    fprintf(stderr,"Start PXIe board test...\n");
    fprintf(stderr,"\n");
    fprintf(stderr,"\n");

    fprintf(stderr,"test board name: %s\n", pxie_board_name);
    fprintf(stderr,"\n");

    // 打开板卡
    errStatus = HITATCI_PXIe_init (pxie_board_name, 0 , 1, &pxie_fd);
    if(errStatus < 0){
        fprintf(stderr,"!!! PXIe %s open err\n", pxie_board_name);
    }

    // 获取板卡信息
    errStatus = HITATCI_PXIe_viDevmsg (pxie_fd, &vendor_id, &pci_device_id, &pci_slot_id, &pci_bus_id);
    fprintf(stderr,"HITATCI_PXIe_viDevmsg status : %d\n", errStatus);
    fprintf(stderr,"HITATCI_PXIe_viDevmsg vendor_id: %x, pci_device_id: %x, pci_slot_id: %x, pci_bus_id: %x\n", \
        errStatus, vendor_id, pci_device_id, pci_slot_id, pci_bus_id);

    // 填充缓冲区
    for(temp_i = 0; temp_i < BUFFER_LEN; temp_i ++){
        rd_from_fpga[temp_i] = 0;
        wr_from_fpga[temp_i] = temp_i;
    }

    // 注意，因为wr_from_fpga为int型，一个int型为4字节，
    // 所以传输的长度应该是wr_from_fpga数组长*4，长度单位为字节
    // 对于  rd_fpga_len同理
    rd_fpga_len = BUFFER_LEN * 4;
    wr_fpga_len = BUFFER_LEN * 4;

    // 向FPGA写入数据
    errStatus = HITATCI_PXIe_viOut32_dma (pxie_fd, 0, 0x0, (ViPUInt32)wr_from_fpga, wr_fpga_len);
    fprintf(stderr,"HITATCI_PXIe_viOut32_dma status : %d\n", errStatus);

    // 从FPGA读取数据
    errStatus = HITATCI_PXIe_viIn32_dma (pxie_fd, 0, 0, (ViPUInt32)rd_from_fpga, rd_fpga_len);
    fprintf(stderr,"HITATCI_PXIe_viIn32_dma status : %d\n", errStatus);

    // 填充缓冲区
    for(temp_i = 0; temp_i < 16; temp_i ++){
        fprintf(stderr,"rd_data: %x, wr_data: %x\n", rd_from_fpga[temp_i], wr_from_fpga[temp_i]);
    }

    // 进行数据判读
    for(temp_i = 0; temp_i < BUFFER_LEN; temp_i ++){
        if(wr_from_fpga[temp_i] != rd_from_fpga[temp_i]){
            fprintf(stderr,"!!! data err, place: %d, rd_data: %x, wr_data: %x\n", temp_i, rd_from_fpga[temp_i], wr_from_fpga[temp_i]);
            break;
        }
    }

    // 写入和和读取的一致，给出提示
    if(temp_i == BUFFER_LEN){
        fprintf(stderr,"read and write data ok\n");
    }
   
    // 关闭板卡
    if (pxie_fd != VI_NULL) {
        errStatus = HITATCI_PXIe_Close(pxie_fd);
        if(errStatus < 0){
            fprintf(stderr,"!!! PXI close err\n");
        }
    }

    fprintf(stderr,"\n");
    fprintf(stderr,"\n");
    fprintf(stderr,"Finish PXIe board test...\n");
    fprintf(stderr,"\n");
    fprintf(stderr,"\n");

    return 0;
}





#ifdef	TST_CODE_SWITCH
	//fprintf(stderr,"judgement_exist_time is :%x\n",judgement_exist_time);
#endif

    /*
    //ioctl操作命令,设置要进行重映射的BAR空间
#define BAR_NUM_SET         0xfee50001

//ioctl操作命令,获取PCI的bus地址
#define PCI_BUS_GET         0xfee50010

//ioctl操作命令,获取厂商ID
#define GET_VENDOR_ID 		0xfee50020

//ioctl操作命令,获取设备ID
#define GET_DEVICE_ID 		0xfee50021

//ioctl操作命令,获取槽位号
#define GET_SLOT_NUM 		0xfee50022

//ioctl操作命令,获取槽位号
#define GET_SLOT_NUM 		0xfee50022

//ioctl操作命令,CPU从寄存器空间读取数据
#define READ_FROM_REG       0xfd000000

//ioctl操作命令,CPU向寄存器空间写入数据
#define WRITE_TO_REG        0xfc000000

//配置设备的读写是否使用DMA控制器
#define USE_DMA             0xfee50030
#define NOT_DMA             0xfee50031

    int fpga_fd, ret;
    unsigned char bar_num;
    unsigned short vendor_id = 0;
	unsigned short pci_device_id = 0;
	unsigned short pci_slot_id = 0;
    unsigned int rd_data, wr_data;
    off_t now_place = 0;
    unsigned int rd_buf[100], wr_buf[100];
    unsigned int rd_len = 0, wr_len = 0;

    //测试打开设备
    fpga_fd = fpga_open("/dev/slot05_11_hitmc0_user");
    printf("fpga_fd :%d\n", fpga_fd);

    //获取设备信息
    vendor_id = fpga_ioctl(fpga_fd, GET_VENDOR_ID, NULL);
    pci_device_id = fpga_ioctl(fpga_fd, GET_DEVICE_ID, NULL);
    pci_slot_id = fpga_ioctl(fpga_fd, GET_SLOT_NUM, NULL);
    printf("vendor_id :%x\n", vendor_id);
    printf("pci_device_id :%x\n", pci_device_id);
    printf("pci_slot_id :%x\n", pci_slot_id);

    //设置操作BAR空间
    bar_num = 2;
    vendor_id = fpga_ioctl(fpga_fd, BAR_NUM_SET, (unsigned long *)&bar_num);
    
    //读写操作使用DMA
    fpga_ioctl(fpga_fd, USE_DMA, NULL);

    //读写操作不使用DMA
    fpga_ioctl(fpga_fd, NOT_DMA, NULL);

    //从FPGA寄存器空间读取数据
    rd_data = 0;
    rd_data = fpga_ioctl(fpga_fd, READ_FROM_REG, NULL);
    printf("1 rd_data :%x\n", rd_data);
*/
/*
    //向FPGA寄存器空间写入数据
    wr_data = rd_data + 0x10;
    fpga_ioctl(fpga_fd, WRITE_TO_REG, (unsigned long *)&wr_data);
    printf("1 wr_data :%x\n", wr_data);

    //从FPGA寄存器空间读取数据
    rd_data = 0;
    rd_data = fpga_ioctl(fpga_fd, READ_FROM_REG, NULL);
    printf("2 rd_data :%x\n", rd_data);


    //从FPGA寄存器空间读取数据
    rd_data = 0;
    rd_data = fpga_ioctl(fpga_fd, READ_FROM_REG, NULL);
    printf("2 rd_data :%x\n", rd_data);

    //设置文件操作位置
    now_place = fpga_lseek(fpga_fd, 0, 0);

    //使用read方法，读取数据
    rd_len = fpga_read(fpga_fd, rd_buf, 1);
    printf("1 rd_buf :%x\n", rd_buf[0]);
    printf("1 rd_len :%x\n", rd_len);

    //使用write方法，读取数据
    rd_buf[0] += 0x20;
    wr_len = fpga_write(fpga_fd, rd_buf, 1);
    printf(" rd_buf :%x\n", rd_buf[0]);
    printf(" wr_len :%x\n", wr_len);

    //使用read方法，读取数据
    rd_len = fpga_read(fpga_fd, rd_buf, 1);
    printf("2 rd_buf :%x\n", rd_buf[0]);
    printf("2 rd_len :%x\n", rd_len);

    //测试关闭设备
    ret = fpga_close(fpga_fd);
    printf("close :%d\n", ret);
*/


/*
    //用户提供的文件描述符
    struct fd_opt fd_opt_value;
    int ret, temp_i;
    unsigned char send_data_buf[20000], rev_data_buf[20000];
    unsigned int send_data_len, rev_data_len;
    unsigned int err_time = 0 , err_data_num = 0, err_flag = 0;
    unsigned int test_num, test_all_time;

    struct timeval start_tv, end_tv;
    long send_diff_time, rev_diff_time;

    //打开设备
    ret = fpga_open(0xfee5, 0x0306, 0);
    printf("open status :%d\n", ret);

    //进行0地址测试
    device_test();

    //复位422设备板卡
    device_rst();

    //复位422第一个芯片
    chip_rst(1);

    //配置1号芯片为异步模
    //device_chip_mode(&fd_opt_value, 1, CHIP_ASYNC_MODE);

    //配置921600bps,8 N 1
    async_parameter_set(&fd_opt_value, 1, 921600, 1, 0, 8);

    //配置1号芯片为同步模式.
    device_chip_mode(1, CHIP_SYNC_MODE);

    //配置通道1,800000bps,8位数据宽度,头7e个数，尾7e个数,时钟方向，数据方向
    sync_parameter_set(1, 800000, 8, 4, 4, 0, 0);
    //ync_parameter_set(&fd_opt_value, 1, 1600000, 8, 4, 4, 0, 0);

    //配置通道2,800000bps,8位数据宽度,头7e个数，尾7e个数,时钟方向，数据方向
    sync_parameter_set(2, 800000, 8, 4, 4, 0, 0);
    //sync_parameter_set(&fd_opt_value, 2, 1600000, 8, 4, 4, 0, 0);

    printf("run test\n");

    //进行同步通信测试
    test_all_time = 0;
    err_time = 0;
    while(1){
        //填充发送长度和发送数据
        send_data_len = 16;
        for(temp_i = 0; temp_i < send_data_len; temp_i ++){
            send_data_buf[temp_i] = temp_i;
        }

        //清空接收数据域
        rev_data_len = send_data_len;
        for(temp_i = 0; temp_i < rev_data_len; temp_i ++){
            rev_data_buf[temp_i] = 0;
        }
        rev_data_len = 0;

        //同步1通道填充数据
        sync_fill_send_data(1, send_data_len, send_data_buf);

        //启动同步第一通道发送
        sync_start_send_data(1, send_data_len);
        //printf("send len:%d\n", send_data_len);

        //延时一会，等待数据接收完毕
        usleep(5000);

        //获取同步2通道接收数据长度
        rev_data_len = 0;
        sync_get_rev_data_len(2, &rev_data_len);

        //读取同步2通道数据
        sync_rev_data_no_dma(2, rev_data_len, rev_data_buf);
        //sync_rev_data_dma(&fd_opt_value, 2, 16, rev_data_buf);

        //清空异常标志
        err_flag = 0;

        //进行数据长度判读
        if(rev_data_len != (send_data_len + 2)){
            printf("!!!err len. send len:%d, rev len:%d\n", send_data_len, rev_data_len);
            err_flag = 1;
        }

        //进行数据判读
        for(temp_i = 0; temp_i < send_data_len; temp_i ++){
            if(send_data_buf[temp_i] != rev_data_buf[temp_i]){
                err_flag = 1;

                printf("!!!err data. place:%d send data:%d, rev data:%d\n", temp_i, send_data_buf[temp_i], rev_data_buf[temp_i]);
                break;
            }
        }

        //进行尾部判读
        if(rev_data_buf[rev_data_len - 2] != 0x47){
            err_flag = 1;
        }

        //进行尾部判读
        if(rev_data_buf[rev_data_len - 1] != 0x0f){
            err_flag = 1;
        }

        if(err_flag == 1){
            err_time ++;
            err_flag = 0;
        }

        //延时一会，等待数据接收完毕
        //usleep(80000);

        test_all_time ++;
        if((test_all_time % 100) == 0x0){
            printf("test num:%d, err_time:%d\n", test_all_time, err_time);
        }

        if(test_all_time >= 36000){
            break;
        }
    }

    printf(" all test num:%d\n", test_all_time);
    //关闭设备
    ret = fpga_close();
    printf("close status:%d\n", ret);
*/
